#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include "serveur.h"
#include "hash_table.h"
#include "client.h"
#include "fichier.h"
#include <arpa/inet.h>
#include "parseur.h"


//#define MAX_CLIENT 5
#define SIZE_MAX_REQ 1024
#define MAX_TEXT_SIZE 40
#define MAX_WORD_SIZE 45

/*Initialisation du Mutex*/
static pthread_mutex_t mutex_possesseur = PTHREAD_MUTEX_INITIALIZER;

void error(char * msg){
    printf(msg);
    exit(1);
}




void * create_socket(void * ss){
  ssize_t n = 0;
  //  int u;
  struct srv *s = (struct srv *) ss;
  fprintf(stderr,"Connexion established with %s\n",s->c->IP);
  //  int mysockfd = s->sock;
  
  char * buffer = malloc(SIZE_MAX_REQ*sizeof(char));
  memset(buffer,0,SIZE_MAX_REQ);

  printf("malloc termine, taille :%d\n",SIZE_MAX_REQ*sizeof(char) );

  /* Lecture de la requete */
  while((n=read(s->sock,buffer,SIZE_MAX_REQ))){
    if(n==-1){
      error("ERROR while reading");
    }
    
    /*  verification s'il y a un \n et ajout d'un espace a la fin de la requete pour parsing plus pratique */
    /* for (u=0;u<strlen(buffer);u++){
      if (strcmp((buffer+u),"\n") == 0){
	strcpy(buffer+u,buffer+(u+1));
      }
      sprintf(buffer+(strlen(buffer))," ");
      }*/
    
    
    
    fprintf(stdout,"parsing selon le type de la  requete\n");

    if(strncmp(buffer,"announce",8)==0){
      pthread_mutex_lock(&mutex_possesseur);
      annonce(buffer,s);
      pthread_mutex_unlock(&mutex_possesseur);
    }
    else if(strcmp(buffer,"look")>0 && buffer[0]=='l'){
      pthread_mutex_lock(&mutex_possesseur);      
      chercher(buffer,s);
      pthread_mutex_unlock(&mutex_possesseur);
    }
    else if(strcmp(buffer,"getfile")>0 && buffer[0]=='g'){
      pthread_mutex_lock(&mutex_possesseur);
      demande(buffer,s);
      pthread_mutex_unlock(&mutex_possesseur);
    }
    else if(strcmp(buffer,"update")>0 && buffer[0]=='u'){
      pthread_mutex_lock(&mutex_possesseur);
      miseAJour(buffer,s);
      pthread_mutex_unlock(&mutex_possesseur);
    }
    
    else if (strcmp(buffer,"quit")>0 && buffer[0]=='q'){ 
      close(s->sock);//mysockfd);
       supprimer_client(s);
       pthread_exit(NULL);
  
     
    }
    
   else {
      printf("not a message \n");
      printf("if you want to quit write quit \n");
    }
    
    
    
    memset(buffer,0,SIZE_MAX_REQ);
    
  }
   pthread_exit(NULL);
   
}

int main(int argc, char * argv[]){
  int i,m;
  //int sockfd;
  if (argc != 2){
    fprintf(stderr,"Usage : %s numeroPort\n",argv[0]);
    exit(1);
  }
  unsigned int portno = atoi(argv[1]);
  //socklen_t clilen;
  struct sockaddr_in serv_addr;
  //struct sockaddr_in cli_addr;

  
  /* Initialisation du tracker */
  /*int sock_tab[MAX_CLIENT];
  for(i=0;i<MAX_CLIENT;i++)
    sock_tab[i] = 0;
  */
  memset((char *) &serv_addr,0, sizeof(serv_addr));
  
  
  //appel de la fonction qui initialise la table de hashage
  struct hash_table* ht = init_table();
  
  pthread_t ** thread_tab = malloc(MAX_CLIENT*sizeof(pthread_t *));
  for(i=0;i<MAX_CLIENT;i++)
    thread_tab[i] = malloc(sizeof(pthread_t));

  clilen = sizeof(cli_addr);
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(portno);
  /* Fin initialisation */


 
  
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) 
     error("ERROR opening socket");
  if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
	error("ERROR on binding");
  listen(sockfd,5);

  i = 0;
  while(i<MAX_CLIENT){
    struct srv * s = malloc(sizeof(*s));
    /*sock_tab[i]*/s->sock = accept(sockfd,(struct sockaddr *) &cli_addr, &clilen);
    if (/*sock_tab[i]*/s->sock < 0) 
      error("ERROR on accept");
    
    s->t=ht;
    //s->sock = sock_tab[i];


    /* Recuperation adresse ip et ajout du host dans le tableau */
    char ip[30];
    strcpy(ip,inet_ntoa(cli_addr.sin_addr));
    // Appel de la fonction qui ajoute le client à la table
    int client = estClient(ip,ht);
    if(client == -1){
      fprintf(stderr,"Create new customer : i = %d\n",i);
      struct client* C = creerClient(ip, portno); 
      fprintf(stderr,"Add customer : i = %d\n",i);
      ajouter_client(ht, C);
      s->c = C;
      i++;
    }
    else
      s->c=ht->tc->tabClient[client];

    fprintf(stderr,"YOOOO");
   
    fprintf(stderr,"Thread create");
    m = pthread_create(thread_tab[i],NULL,create_socket,s);
    if(0 != m)
      error("ERROR creating thread");

  }
  /*
  for(i=0;i<MAX_CLIENT;i++)
    close(sock_tab[i]);
  */
  close(sockfd);

  return EXIT_SUCCESS;

}
